package com.it.aspect;

import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONUtil;
import com.it.annotation.SystemLog;
import com.it.bean.OperationLog;
import com.it.mapper.OperationLogMapper;
import com.it.utils.AppUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * @author TBH
 * @date 2025-05-16 17:22:49
 * @desc
 */
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class SysLogAspect {

    private final OperationLogMapper operationLogMapper;

    @Around(value = "@annotation(com.it.annotation.SystemLog) && @annotation(systemLog)")
    public Object recordLog(ProceedingJoinPoint joinPoint, SystemLog systemLog) throws Throwable {
        // 获取请求信息
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        OperationLog operationLog = new OperationLog();
        operationLog.setController(systemLog.value());
        operationLog.setMethod(systemLog.method());
        operationLog.setUri(request.getRequestURI());
        operationLog.setHttpMethod(request.getMethod());
        operationLog.setParams(JSONUtil.toJsonStr(getParams(joinPoint.getArgs())));
        operationLog.setIp(ServletUtil.getClientIP(request));

        long startTime = System.currentTimeMillis();
        Object result = null;
        try {
            // 执行目标方法
            result = joinPoint.proceed();
            operationLog.setSuccess(Boolean.TRUE);
        } catch (Exception e) {
            operationLog.setSuccess(Boolean.FALSE);
            operationLog.setErrorMsg(e.getMessage());
            throw e; // 重新抛出异常，保证业务逻辑不受影响
        } finally {
            long endTime = System.currentTimeMillis();
            operationLog.setExecutionTime((endTime - startTime) + "ms");
            AppUtils.forSaveAudit(operationLog);
            operationLogMapper.insert(operationLog);
        }
        return result;
    }

    private Object getParams(Object[] args) {
        if (args == null || args.length == 0) {
            return null;
        }

        Object[] params = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof HttpServletRequest || args[i] instanceof HttpServletResponse) {
                continue;
            }
            params[i] = args[i];
        }
        return params;
    }
}
